package cn.jbolt.core.kit;

import cn.jbolt.core.api.JBoltApiJwtManger;
import cn.jbolt.core.api.JBoltApiKit;
import cn.jbolt.core.api.JBoltApiRet;
import cn.jbolt.core.base.JBoltMsg;
import cn.jbolt.core.base.JBoltRequestType;
import cn.jbolt.core.base.config.JBoltConfig;
import cn.jbolt.core.bean.JBoltDateRange;
import cn.jbolt.core.bean.RangeSlider;
import cn.jbolt.core.consts.JBoltConst;
import cn.jbolt.core.crossorigin.CrossOrigin;
import cn.jbolt.core.para.JBoltPara;
import cn.jbolt.core.para.jbolttablemenufilter.JBoltTableMenuFilter;
import cn.jbolt.core.para.jbolttablemenufilter.JBoltTableMenuFilterItem;
import cn.jbolt.core.ui.jbolttable.JBoltTable;
import cn.jbolt.core.ui.jbolttable.JBoltTableMulti;
import cn.jbolt.core.util.JBoltArrayUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.core.Action;
import com.jfinal.core.Controller;
import com.jfinal.core.converter.TypeConverter;
import com.jfinal.json.JFinalJson;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;
import com.jfinal.render.ContentType;
import com.jfinal.render.RenderException;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

/**
 * controller层公用工具类
 *
 * @ClassName: ControllerKit
 * @author: JFinal学院-小木 QQ：909854136
 * @date: 2019年9月17日
 */
public class JBoltControllerKit {
	private static final Log JBOLT_API_LOG = Log.getLog("JBoltApiLog");
	private static final Log LOG = Log.getLog(JBoltControllerKit.class);
	/**
	 * 成功返回值 默认
	 */
	private static final Ret JSON_SUCCESS = Ret.ok();

	/**
	 * AjaxPortal请求返回错误信息
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderAjaxPortalFail(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/portalerror.html");
	}

	/**
	 * AjaxPortal请求返回成功信息
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderAjaxPortalSuccess(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/portalsuccess.html");
	}

	/**
	 * 判断是否是Ajax请求
	 *
	 * @return
	 */
	public static boolean isAjax(Controller controller) {
		return JBoltRequestType.AJAX.equals(controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE));
	}
	/**
	 * 判断是否是JSON请求
	 *
	 * @return
	 */
	public static boolean isJsonRequest(Controller controller) {
		return JBoltRequestType.JSON.equals(controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE));
	}

	/**
	 * 判断是否是normal请求
	 *
	 * @return
	 */
	public static boolean isNormal(Controller controller) {
		return JBoltRequestType.NORMAL.equals(controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE));
	}

	/**
	 * 判断是否是dialog请求
	 *
	 * @return
	 */
	public static boolean isDialog(Controller controller) {
		return JBoltRequestType.DIALOG.equals(controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE));
	}

	/**
	 * 判断是否是iframe请求
	 *
	 * @return
	 */
	public static boolean isIframe(Controller controller) {
		return JBoltRequestType.IFRAME.equals(controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE));
	}

	/**
	 * 判断请求是否是Pjax请求
	 *
	 * @return
	 */
	public static boolean isPjax(Controller controller) {
		return JBoltRequestType.PJAX.equals(controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE));
	}

	/**
	 * 判断请求是否是ajaxPortal请求
	 *
	 * @return
	 */
	public static boolean isAjaxPortal(Controller controller) {
		return JBoltRequestType.AJAXPORTAL.equals(controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE));
	}

	/**
	 * 判断请求是否是Jbolt Api请求
	 *
	 * @return
	 */
	public static boolean isCallJBoltApi(Controller controller) {
		return JBoltRequestType.JBOLTAPI.equals(controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE));
	}

	/**
	 * pjax请求返回错误信息片段
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderPjaxFail(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/pjaxerror.html");
	}

	/**
	 * pjax请求返回成功信息片段
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderPjaxSuccess(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/pjaxsuccess.html");
	}

	/**
	 * form提交跳转 表单跳转到错误信息显示
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderFormFail(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/formerror.html");
	}

	/**
	 * 链接页面跳转 错误信息显示
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderPageFail(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/pagefail.html");
	}

	/**
	 * 链接页面跳转 成功显示
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderPageSuccess(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/pagesuccess.html");
	}

	/**
	 * 链接页面跳转 错误信息显示 H5移动场景使用
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderH5PageFail(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_common/h5/msg/pagefail.html");
	}

	/**
	 * 链接页面跳转 成功显示 H5移动场景使用
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderH5PageSuccess(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_common/h5/msg/pagesuccess.html");
	}

	/**
	 * 返回失败信息 json格式
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderJsonFail(Controller controller, String msg) {
		renderJsonFail(controller, msg, null);
	}

	/**
	 * 返回失败信息 json格式
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 */
	public static void renderJsonFail(Controller controller, String msg, Object data) {
		renderJsonFail(controller,msg,data,false);
	}

	/**
	 * 返回失败信息 json格式
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 * @param useJfinalJson 是否使用jfinaljson
	 */
	public static void renderJsonFail(Controller controller, String msg, Object data,boolean useJfinalJson) {
		if(useJfinalJson){
			controller.renderJson(JFinalJson.getJson().toJson(Ret.fail(msg).setIfNotNull("data", data)));
		}else{
			controller.renderJson(Ret.fail(msg).setIfNotNull("data", data));
		}
	}

//	/**
//	 * 拦截器层 根据request类型响应不同错误信息
//	 * @param controller
//	 * @param msg
//	 */
//	public static void renderInterceptorErrorInfo(Controller controller,String msg) {
//		renderError(controller, msg);
//	}
	/**
	 * 拦截器返回未登录错误信息
	 *
	 * @param controller
	 */
	public static void renderAdminInterceptorNotLoginInfo(Controller controller) {
		String rqType = controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE);
		if (StrKit.isBlank(rqType)) {
			// 判断如果没有登录 需要跳转到登录页面
			toAdminLogin(controller);
			return;
		}
		switch (rqType) {
		case JBoltRequestType.JBOLTAPI:
			renderJBoltApiRet(controller, JBoltApiRet.NOT_ADMIN_LOGIN(JBoltApiKit.getApplication()));
			break;
		case JBoltRequestType.AJAX:
			renderJsonFail(controller, "jbolt_nologin");
			break;
		case JBoltRequestType.JSON:
			renderJsonFail(controller, "jbolt_nologin");
			break;
		case JBoltRequestType.PJAX:
			renderPjaxFail(controller, JBoltMsg.ADMIN_NO_LOGIN_INFO);
			break;
		case JBoltRequestType.AJAXPORTAL:
			renderAjaxPortalFail(controller, JBoltMsg.ADMIN_AJAXPORTAL_NO_LOGIN_INFO);
			break;
		case JBoltRequestType.DIALOG:
			toAdminLogin(controller);
			break;
		case JBoltRequestType.IFRAME:
			toAdminLogin(controller);
			break;
		case JBoltRequestType.NORMAL:
			toAdminLogin(controller);
			break;
		case JBoltRequestType.NULL:
			renderJsonFail(controller, "jbolt_nologin");
			break;
		default:
			renderJsonFail(controller, "jbolt_nologin");
			break;
		}
	}

	/**
	 * 拦截器返回异端顶替错误信息
	 *
	 * @param controller
	 */
	public static void renderAdminInterceptorTerminalOfflineInfo(Controller controller) {
		String rqType = controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE);
		if (StrKit.isBlank(rqType)) {
			// 判断如果没有登录 需要跳转到登录页面
			toTerminalOfflinePage(controller);
			return;
		}
		switch (rqType) {
		case JBoltRequestType.JBOLTAPI:
			renderJBoltApiRet(controller, JBoltApiRet.TERMINAL_OFFLINE(JBoltApiKit.getApplication()));
			break;
		case JBoltRequestType.AJAX:
			renderJsonFail(controller, "jbolt_terminal_offline");
			break;
		case JBoltRequestType.JSON:
			renderJsonFail(controller, "jbolt_terminal_offline");
			break;
		case JBoltRequestType.PJAX:
			renderPjaxFail(controller, JBoltMsg.ADMIN_TERMINAL_OFFLINE_INFO);
			break;
		case JBoltRequestType.AJAXPORTAL:
			renderAjaxPortalFail(controller, JBoltMsg.ADMIN_AJAXPORTAL_TERMINAL_OFFLINE_INFO);
			break;
		case JBoltRequestType.DIALOG:
			toTerminalOfflinePage(controller);
			break;
		case JBoltRequestType.IFRAME:
			toTerminalOfflinePage(controller);
			break;
		case JBoltRequestType.NORMAL:
			toTerminalOfflinePage(controller);
			break;
		case JBoltRequestType.NULL:
			renderJsonFail(controller, "jbolt_terminal_offline");
			break;
		default:
			renderJsonFail(controller, "jbolt_terminal_offline");
			break;
		}
	}

	/**
	 * 拦截器返回强退下线错误信息
	 *
	 * @param controller
	 */
	public static void renderAdminInterceptorForcedOfflineInfo(Controller controller) {
		String rqType = controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE);
		if (StrKit.isBlank(rqType)) {
			// 判断如果没有登录 需要跳转到登录页面
			toForcedOfflinePage(controller);
			return;
		}
		switch (rqType) {
		case JBoltRequestType.JBOLTAPI:
			renderJBoltApiRet(controller, JBoltApiRet.FORCED_OFFLINE(JBoltApiKit.getApplication()));
			break;
		case JBoltRequestType.AJAX:
			renderJsonFail(controller, JBoltMsg.ADMIN_FORCED_OFFLINE_PAGE_MSG);
			break;
		case JBoltRequestType.JSON:
			renderJsonFail(controller, JBoltMsg.ADMIN_FORCED_OFFLINE_PAGE_MSG);
			break;
		case JBoltRequestType.PJAX:
			renderPjaxFail(controller, JBoltMsg.ADMIN_FORCED_OFFLINE_PAGE_MSG);
			break;
		case JBoltRequestType.AJAXPORTAL:
			renderAjaxPortalFail(controller, JBoltMsg.ADMIN_FORCED_OFFLINE_PAGE_MSG);
			break;
		case JBoltRequestType.DIALOG:
			toForcedOfflinePage(controller);
			break;
		case JBoltRequestType.IFRAME:
			toForcedOfflinePage(controller);
			break;
		case JBoltRequestType.NORMAL:
			toForcedOfflinePage(controller);
			break;
		case JBoltRequestType.NULL:
			renderJsonFail(controller, JBoltMsg.ADMIN_FORCED_OFFLINE_PAGE_MSG);
			break;
		default:
			renderJsonFail(controller, JBoltMsg.ADMIN_FORCED_OFFLINE_PAGE_MSG);
			break;
		}
	}

	/**
	 * 调用 API的应用返回结果
	 *
	 * @param controller
	 * @param jboltApiRet
	 */
	public static void renderJBoltApiRet(Controller controller, JBoltApiRet jboltApiRet) {
		if (jboltApiRet.isFail()) {
			// 单独处理错误日志
			JBOLT_API_LOG.error("[{}] {}", controller.getClass().getName(),JsonKit.toJson(jboltApiRet));
		}
		controller.renderJson(jboltApiRet);
	}

	/**
	 * 调用 API的应用返回结果
	 *
	 * @param controller
	 * @param jboltApiRet
	 * @param useJfinalJson 是否使用jfinalJson
	 */
	public static void renderJBoltApiRet(Controller controller, JBoltApiRet jboltApiRet, boolean useJfinalJson) {
		if (jboltApiRet.isFail()) {
			// 单独处理错误日志
			JBOLT_API_LOG.error("[{}] {}", controller.getClass().getName(),JsonKit.toJson(jboltApiRet));
		}
		if(useJfinalJson){
			controller.renderJson(JFinalJson.getJson().toJson(jboltApiRet));
		}else{
			controller.renderJson(jboltApiRet);
		}
	}

	/**
	 * 调用 API的应用返回结果
	 *
	 * @param controller
	 * @param ret
	 * @param useJfinalJson
	 */
	public static void renderJBoltApiRet(Controller controller, Ret ret,boolean useJfinalJson) {
		if (ret.isFail()) {
			renderJBoltApiFail(controller, ret.getStr("msg"), ret.get("data"),useJfinalJson);
		} else {
			renderJBoltApiSuccess(controller, ret.getStr("msg"), ret.get("data"),useJfinalJson);
		}
	}

	/**
	 * 调用 API的应用返回结果
	 *
	 * @param controller
	 * @param ret
	 */
	public static void renderJBoltApiRet(Controller controller, Ret ret) {
		renderJBoltApiRet(controller,ret,false);
	}

	/**
	 * 调用 API的应用返回结果 fail
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderJBoltApiFail(Controller controller, String msg) {
		renderJBoltApiRet(controller, JBoltApiRet.API_FAIL(JBoltApiKit.getApplication(), msg));
	}

	/**
	 * 调用 API的应用返回结果 success data
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 */
	public static void renderJBoltApiSuccess(Controller controller, String msg, Object data) {
		renderJBoltApiSuccess(controller,msg,data,false);
	}

	/**
	 * 调用 API的应用返回结果 success data
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 * @param useJfinalJson 是否使用JFinalJson
	 */
	public static void renderJBoltApiSuccess(Controller controller, String msg, Object data,boolean useJfinalJson) {
		renderJBoltApiRet(controller, JBoltApiRet.API_SUCCESS(msg, data), useJfinalJson);
	}

	/**
	 * 调用 API的应用返回结果 fail data
	 *
	 * @param controller
	 * @param data
	 */
	public static void renderJBoltApiFail(Controller controller, String msg, Object data) {
		renderJBoltApiFail(controller,msg,data,false);
	}

	/**
	 * 调用 API的应用返回结果 fail data
	 *
	 * @param controller
	 * @param data
	 * @param useJfinalJson 是否使用JFinalJson
	 */
	public static void renderJBoltApiFail(Controller controller, String msg, Object data,boolean useJfinalJson) {
		renderJBoltApiRet(controller, JBoltApiRet.API_FAIL(JBoltApiKit.getApplication(), msg, data), useJfinalJson);
	}

	/**
	 * 调用 API的应用返回结果 success
	 *
	 * @param controller
	 */
	public static void renderJBoltApiSuccess(Controller controller) {
		renderJBoltApiRet(controller, JBoltApiRet.API_SUCCESS);
	}

	/**
	 * 跳转到登录页面
	 */
	public static void toAdminLogin(Controller controller) {
		controller.redirect(JBoltConst.JBOLT_ADMIN_LOGIN_ACTION_KEY);
	}

	/**
	 * 跳转到异端登录提示
	 */
	public static void toTerminalOfflinePage(Controller controller) {
		controller.redirect(JBoltConst.JBOLT_ADMIN_TERMINAL_OFFLINE_ACTION_KEY);
	}

	/**
	 * 跳转到强退提示
	 */
	public static void toForcedOfflinePage(Controller controller) {
		controller.redirect(JBoltConst.JBOLT_ADMIN_FORCED_OFFLINE_ACTION_KEY);
	}

	/**
	 * 返回Validator错误信息
	 *
	 * @param controller
	 */
	public static void renderValidatorError(Controller controller) {
		if (isCallJBoltApi(controller)) {
			renderJBoltApiFail(controller, controller.getAttr("msg"));
		} else if (isPjax(controller)) {
			renderPjaxFail(controller, controller.getAttr("msg"));
		} else if (isAjaxPortal(controller)) {
			renderAjaxPortalFail(controller, controller.getAttr("msg"));
		} else if (isAjax(controller)) {
			renderJsonFail(controller, controller.getAttr("msg"));
		} else {
			renderDialogFail(controller, controller.getAttr("msg"));
		}
	}

	/**
	 * 设置msg信息
	 *
	 * @param controller
	 * @param msg
	 */
	public static void setMsg(Controller controller, String msg) {
		controller.set("msg", msg);
	}

	/**
	 * Dialog中跳转错误页面
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderDialogFail(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/dialogerror.html");
	}

	/**
	 * Dialog中跳转成功页面
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderDialogSuccess(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/dialogsuccess.html");
	}

	/**
	 * Iframe中跳转成功页面
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderIframeSuccess(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/iframesuccess.html");
	}

	/**
	 * IFrame中跳转错误失败信息页面
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderIframeFail(Controller controller, String msg) {
		setMsg(controller, msg);
		controller.render("/_view/_admin/common/msg/iframeerror.html");
	}

	/**
	 * 返回404错误信息
	 *
	 * @param controller
	 */
	public static void render404Error(Controller controller) {
		renderFail(controller, JBoltMsg.ERROR_404_NOTFOUND);
	}

	/**
	 * render 锁屏消息
	 *
	 * @param controller
	 */
	public static void renderAdminSystemLockedInfo(Controller controller) {
		renderFail(controller, JBoltMsg.JBOLT_SYSTEM_LOCKED);
	}

	/**
	 * render 锁屏消息
	 *
	 * @param controller
	 */
	public static void renderSystemLockedPage(Controller controller) {
		controller.render("/_view/_admin/common/msg/systemlocked.html");
	}

	/**
	 * render 失败错误信息
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderFail(Controller controller, String msg) {
		renderFail(controller, msg, null);
	}

	/**
	 * render 失败错误信息
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 */
	public static void renderFail(Controller controller, String msg, Object data) {
		renderFail(controller,msg,data,false);
	}
	/**
	 * render 失败错误信息
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 * @param useJfinalJson
	 */
	public static void renderFail(Controller controller, String msg, Object data,boolean useJfinalJson) {
		String rqType = controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE);
		LOG.info("renderFail rqType:"+rqType);
		if (StrKit.isBlank(rqType)) {
			renderPageFail(controller, msg);
			return;
		}
		switch (rqType) {
		case JBoltRequestType.JBOLTAPI:
			renderJBoltApiFail(controller, msg, data,useJfinalJson);
			break;
		case JBoltRequestType.AJAX:
			renderJsonFail(controller, msg, data,useJfinalJson);
			break;
		case JBoltRequestType.JSON:
			renderJsonFail(controller, msg, data,useJfinalJson);
			break;
		case JBoltRequestType.PJAX:
			renderPjaxFail(controller, msg);
			break;
		case JBoltRequestType.AJAXPORTAL:
			renderAjaxPortalFail(controller, msg);
			break;
		case JBoltRequestType.DIALOG:
			renderDialogFail(controller, msg);
			break;
		case JBoltRequestType.IFRAME:
			renderIframeFail(controller, msg);
			break;
		case JBoltRequestType.NORMAL:
			renderPageFail(controller, msg);
			break;
		case JBoltRequestType.NULL:
			renderJsonFail(controller, msg, data,useJfinalJson);
			break;
		default:
			renderJsonFail(controller, msg, data,useJfinalJson);
			break;
		}
	}

	/**
	 * render confirm确认信息
	 *
	 * @param controller
	 * @param msg
	 * @param optUrl
	 * @param reqType
	 * @param data
	 */
	public static void renderJsonConfirm(Controller controller,String msg, String optUrl,String reqType, Object data,boolean useJfinalJson) {
		if(StrKit.isBlank(msg)){
			throw new RuntimeException("请指定confirm msg信息");
		}
		if(StrKit.isBlank(optUrl)){
			throw new RuntimeException("请指定confirm 后提交的地址optUrl");
		}
		if(StrKit.isBlank(reqType)){
			throw new RuntimeException("请指定confirm 后提交的请求类型reqType GET POST DOWNLOAD");
		}
		Ret ret = Ret.ok(msg).set("needConfirm",true).set("optUrl",optUrl).set("reqType",reqType).setIfNotNull("data", data);
		if(useJfinalJson){
			controller.renderJson(JFinalJson.getJson().toJson(ret));
		}else{
			controller.renderJson(ret);
		}
	}
	/**
	 * render 成功信息
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 */
	public static void renderSuccess(Controller controller, String msg, Object data) {
		renderSuccess(controller,msg,data,false);
	}
	/**
	 * render 成功信息
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 * @param useJfinalJson
	 */
	public static void renderSuccess(Controller controller, String msg, Object data,boolean useJfinalJson) {
		String rqType = controller.getAttr(JBoltConst.RQKEY_JB_RQTYPE);
		if (StrKit.isBlank(rqType)) {
			renderPageFail(controller, msg);
			return;
		}
		switch (rqType) {
		case JBoltRequestType.JBOLTAPI:
			renderJBoltApiSuccess(controller, msg, data,useJfinalJson);
			break;
		case JBoltRequestType.AJAX:
			renderJsonSuccess(controller, msg, data,useJfinalJson);
			break;
		case JBoltRequestType.JSON:
			renderJsonSuccess(controller, msg, data,useJfinalJson);
			break;
		case JBoltRequestType.PJAX:
			renderPjaxSuccess(controller, msg);
			break;
		case JBoltRequestType.AJAXPORTAL:
			renderAjaxPortalSuccess(controller, msg);
			break;
		case JBoltRequestType.DIALOG:
			renderDialogSuccess(controller, msg);
			break;
		case JBoltRequestType.IFRAME:
			renderIframeSuccess(controller, msg);
			break;
		case JBoltRequestType.NORMAL:
			renderPageSuccess(controller, msg);
			break;
		case JBoltRequestType.NULL:
			renderJsonSuccess(controller, msg, data,useJfinalJson);
			break;
		default:
			renderJsonSuccess(controller, msg, data,useJfinalJson);
			break;
		}
	}

	/**
	 * 返回正确json result
	 *
	 * @param controller
	 */
	public static void renderJsonSuccess(Controller controller) {
		controller.renderJson(JSON_SUCCESS);
	}

	/**
	 * 返回正确json result 以及Msg
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderJsonSuccess(Controller controller, String msg) {
		controller.renderJson(Ret.ok(msg));
	}
	/**
	 * 返回正确json result 以及Msg data
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 */
	public static void renderJsonSuccess(Controller controller, String msg, Object data) {
		renderJsonSuccess(controller,msg,data,false);
	}

	/**
	 * 返回正确json result 以及Msg data
	 *
	 * @param controller
	 * @param msg
	 * @param data
	 * @param useJfinalJson
	 */
	public static void renderJsonSuccess(Controller controller, String msg, Object data,boolean useJfinalJson) {
		if(useJfinalJson){
			controller.renderJson(JFinalJson.getJson().toJson(Ret.ok(msg).setIfNotNull("data", data)));
		}else{
			controller.renderJson(Ret.ok(msg).setIfNotNull("data", data));
		}
	}

	/**
	 * 返回正确json result 并带着特殊数据
	 *
	 * @param controller
	 * @param data
	 */
	public static void renderJsonData(Controller controller, Object data) {
		renderJsonData(controller,data,false);
	}

	/**
	 * 返回正确json result 并带着特殊数据 底层使用jfinaljson
	 *
	 * @param controller
	 * @param data
	 * @param useJfinalJson
	 */
	public static void renderJsonData(Controller controller, Object data,boolean useJfinalJson) {
		if(useJfinalJson){
			controller.renderJson(JFinalJson.getJson().toJson(Ret.ok().setIfNotNull("data", data)));
		}else{
			controller.renderJson(Ret.ok().setIfNotNull("data", data));
		}
	}

	/**
	 * 处理跨域
	 *
	 * @param controller
	 * @param method
	 */
	public static void processCrossOrigin(Controller controller, Method method) {
		if (JBoltConfig.JBOLT_GLOBAL_CROSS_ORIGIN_ENABLE || checkNeedCrossOrigin(controller, method)) {
			handlerCrossOrigin(controller.getResponse());
		}
	}

	/**
	 * 检查是否跨域
	 *
	 * @param controller
	 * @param method
	 */
	public static boolean checkNeedCrossOrigin(Controller controller, Method method) {
		return controller.getClass().isAnnotationPresent(CrossOrigin.class)
				|| method.isAnnotationPresent(CrossOrigin.class);
	}

	/**
	 * response 设置跨域
	 *
	 * @param response
	 */
	public static void handlerCrossOrigin(HttpServletResponse response) {
		// 如果把Cookie发到服务端，需指定Access-Control-Allow-Credentials=true;
		// response.setHeader("Access-Control-Allow-Credentials", "true");
		// 允许跨域的域名，*号为允许所有,存在被 DDoS攻击的可能。
		response.setHeader("Access-Control-Expose-Headers", JBoltApiJwtManger.JBOLT_API_TOKEN_KEY+","+JBoltApiJwtManger.JBOLT_API_REFRESH_TOKEN_KEY+",websockettoken,jbcapkey,content-disposition");
		response.setHeader("Access-Control-Allow-Origin", "*");
		response.setHeader("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE,PATCH,OPTIONS,HEAD,TRACE");
		response.setHeader("Access-Control-Max-Age", "86400");
		response.setHeader("Access-Control-Allow-Headers",
				"Origin,Accept,Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With,AJAX-PORTAL,JBOLTAPI,jboltappid,jboltjwt,jboltrefreshjwt,jboltsignature,jboltnonce,jbolttimestamp,websockettoken,jbcapkey");
		// IE8 XDomainRequest跨站数据获取功能 兼容IE
		response.setHeader("XDomainRequestAllowed", "1");
	}

	/**
	 * 设置API响应中的JWT
	 *
	 * @param controller
	 * @param jwt
	 * @param refreshJwt
	 * @param inHeader
	 */
	public static void setApiJwts(Controller controller, String jwt, String refreshJwt,boolean inHeader) {
		if(inHeader){
			// 设置到response header里 jwt
			controller.getResponse().setHeader(JBoltApiJwtManger.JBOLT_API_TOKEN_KEY, jwt);
			// 设置到response header里里 refresh jwt
			controller.getResponse().setHeader(JBoltApiJwtManger.JBOLT_API_REFRESH_TOKEN_KEY, refreshJwt);
		}else{
			// 设置到request attr里 jwt
			controller.set(JBoltApiJwtManger.JBOLT_API_TOKEN_KEY, jwt);
			// 设置到request attr里 refresh jwt
			controller.set(JBoltApiJwtManger.JBOLT_API_REFRESH_TOKEN_KEY, refreshJwt);
		}

	}

	/**
	 * 从请求里获取JBoltPara
	 *
	 * @param controller
	 * @return
	 */
	public static JBoltPara getJBoltPara(Controller controller) {
		return getJBoltPara(null, controller);
	}

	/**
	 * 从请求里获取JBoltPara
	 *
	 * @param action
	 * @param controller
	 * @return
	 */
	public static JBoltPara getJBoltPara(Action action, Controller controller) {
		String reqMethod = controller.getRequest().getMethod();
		JBoltPara para = null;
		String contentType = controller.getRequest().getContentType();
		if (StrKit.notBlank(contentType) && contentType.startsWith("application/json")) {
			para = new JBoltPara(controller.getRawData());
		}else {
			para = new JBoltPara(controller.getParaMap());
		}
		return para;
	}

	/**
	 * 从请求里获取getJBoltTableMenuFilter
	 *
	 * @param controller
	 * @return
	 */
	public static JBoltTableMenuFilter getJBoltTableMenuFilter(Controller controller) {
		return getJBoltTableMenuFilter(null, controller);
	}

	/**
	 * 从请求里获取JBoltTableMenuFilter
	 *
	 * @param action
	 * @param controller
	 * @return
	 */
	public static JBoltTableMenuFilter getJBoltTableMenuFilter(Action action, Controller controller) {
		JBoltPara para = getJBoltPara(controller);
		if (para == null || para.isEmpty()) {
			return null;
		}
		Boolean isMenuFilter = para.getBoolean("isMenuFilter");
		if (isMenuFilter == null || !isMenuFilter) {
			return null;
		}
		JBoltTableMenuFilter filter = new JBoltTableMenuFilter();
		if (para.containsKey("filterItems")) {
			JSONArray filterItems = para.getJSONArray("filterItems");
			if (filterItems != null && !filterItems.isEmpty()) {
				filter.setItems(filterItems.toJavaList(JBoltTableMenuFilterItem.class));
			}
		}
		if (para.containsKey("paging")) {
			filter.setPaging(para.getBooleanValue("paging"));
			if (filter.getPaging()) {
				if (para.containsKey("pageSize")) {
					Integer pageSize = para.getInteger("pageSize");
					if (pageSize == null || pageSize.intValue() <= 0) {
						pageSize = 10;
					}
					filter.setPageSize(pageSize);
				} else {
					filter.setPageSize(10);
				}
				int pageNumber = para.getIntValue("page");
				if (pageNumber <= 0) {
					pageNumber = 1;
				}
				filter.setPageNumber(pageNumber);
			}
		}
		if (para.containsKey("sortColumn")) {
			String sortColumn = para.getString("sortColumn");
			if (StrKit.notBlank(sortColumn)) {
				filter.setSortColumn(sortColumn);
				String sortType = para.getString("sortType");
				if (StrKit.isBlank(sortType) || ("desc".equals(sortType))) {
					sortType = "asc";
				}
				filter.setSortType(sortType);
			}
		}
		if (para.containsKey("keywords")) {
			String keywords = para.getString("keywords");
			if (StrKit.notBlank(keywords)) {
				filter.setKeywords(keywords);
				filter.setInclude(para.getBooleanValue("include"));
			}
		}
		return filter;
	}

	/**
	 * 判断是否为预检行为请求
	 *
	 * @param reqMethod
	 * @return
	 */
	public static boolean isOptions(String reqMethod) {
		return reqMethod.equalsIgnoreCase("OPTIONS");
	}

	/**
	 * 获取Json数据
	 *
	 * @return
	 */
	public static JSONObject getJSONObject(Controller controller) {
		String json = controller.getRawData();
		if (StrKit.isBlank(json)) {
			return null;
		}
		return JSON.parseObject(json);
	}

	/**
	 * 获取Json数据转为JSonArray
	 *
	 * @return
	 */
	public static JSONArray getJSONArray(Controller controller) {
		String json = controller.getRawData();
		if (StrKit.isBlank(json)) {
			return null;
		}
		return JSON.parseArray(json);
	}

	/**
	 * 获取Json数据转为JSonArray
	 *
	 * @return
	 */
	public static List<JSONObject> getJSONObjectList(Controller controller) {
		String json = controller.getRawData();
		if (StrKit.isBlank(json)) {
			return null;
		}
		JSONArray jsonArray = JSON.parseArray(json);
		if (jsonArray == null) {
			return null;
		}

		return jsonArrayToObjectList(jsonArray);
	}

	/**
	 * 将jsonarray转为List<JSONObject>
	 *
	 * @param jsonArray
	 * @return
	 */
	private static List<JSONObject> jsonArrayToObjectList(JSONArray jsonArray) {
		int size = jsonArray.size();
		List<JSONObject> jsonObjects = new ArrayList<JSONObject>();
		for (int i = 0; i < size; i++) {
			jsonObjects.add(jsonArray.getJSONObject(i));
		}
		return jsonObjects;
	}

	/**
	 * 获取Json数据 转为Java List
	 *
	 * @return
	 */
	public static <T> List<T> getJSONList(Controller controller, Class<T> clazz) {
		String json = controller.getRawData();
		if (StrKit.isBlank(json)) {
			return null;
		}
		return JSON.parseArray(json, clazz);
	}

	/**
	 * 根据key获取json数据 转为JSONObject
	 *
	 * @param key
	 * @return
	 */
	public static JSONObject getJSONObject(Controller controller, String key) {
		if (StrKit.isBlank(key)) {
			return null;
		}
		JSONObject jsonObject = getJSONObject(controller);
		if (jsonObject == null) {
			return null;
		}
		return jsonObject.getJSONObject(key);
	}

	/**
	 * 根据key获取json数据 转为JSONArray
	 *
	 * @param key
	 * @return
	 */
	public static JSONArray getJSONArray(Controller controller, String key) {
		if (StrKit.isBlank(key)) {
			return null;
		}
		JSONObject jsonObject = getJSONObject(controller);
		if (jsonObject == null) {
			return null;
		}
		return jsonObject.getJSONArray(key);
	}

	/**
	 * 根据key获取json数据 转为List<JSONObject>
	 *
	 * @param key
	 * @return
	 */
	public static List<JSONObject> getJSONObjectList(Controller controller, String key) {
		if (StrKit.isBlank(key)) {
			return null;
		}
		JSONArray jsonArray = getJSONArray(controller, key);
		if (jsonArray == null) {
			return null;
		}
		return jsonArrayToObjectList(jsonArray);
	}

	/**
	 * 根据key获取json数据 转为java List
	 *
	 * @param key
	 * @return
	 */
	public static <T> List<T> getJSONList(Controller controller, String key, Class<T> clazz) {
		if (StrKit.isBlank(key)) {
			return null;
		}
		JSONArray jsonArray = getJSONArray(controller, key);
		if (jsonArray == null) {
			return null;
		}
		return jsonArray.toJavaList(clazz);
	}

	/**
	 * 获取多个JBoltTable组件 提交的数据
	 *
	 * @param controller
	 * @return
	 */
	public static JBoltTableMulti getJBoltTables(Controller controller) {
		// 从请求里获取json字符串
		String jboltTablesJsonStr = controller.get(JBoltTableMulti.PARAM_KEY);
		if (StrKit.isBlank(jboltTablesJsonStr)) {
			return null;
		}
		JSONObject jsonObject = JSON.parseObject(jboltTablesJsonStr);
		if (jsonObject == null || jsonObject.isEmpty()) {
			return null;
		}
		JBoltTableMulti tables = new JBoltTableMulti();
		jsonObject.keySet().forEach(key -> {
			tables.put(key, getJBoltTableByJsonObject(jsonObject.getJSONObject(key)));
		});
		return tables;
	}

	/**
	 * 通过传递的json数据转为JBoltTable
	 *
	 * @param jsonObject
	 * @return
	 */
	private static JBoltTable getJBoltTableByJsonObject(JSONObject jsonObject) {
		JBoltTable jBoltTable = new JBoltTable();
		if (jsonObject.containsKey("delete")) {
			JSONArray jsonArray = jsonObject.getJSONArray("delete");
			if (jsonArray != null && jsonArray.isEmpty() == false) {
				jBoltTable.setDelete(jsonArray.toArray(new Object[jsonArray.size()]));
			}

		}
		if (jsonObject.containsKey("update")) {
			jBoltTable.setUpdate(jsonObject.getJSONArray("update"));
		}
		if (jsonObject.containsKey("save")) {
			jBoltTable.setSave(jsonObject.getJSONArray("save"));
		}
		if (jsonObject.containsKey("form")) {
			jBoltTable.setForm(jsonObject.getJSONObject("form"));
		}
		if (jsonObject.containsKey("params")) {
			jBoltTable.setParams(jsonObject.getJSONObject("params"));
		}
		return jBoltTable;
	}

	/**
	 * 获取JBoltTable组件 提交的数据
	 *
	 * @param controller
	 * @return
	 */
	public static JBoltTable getJBoltTable(Controller controller) {
		// 从请求里获取json字符串
		String jboltTableJsonStr = controller.get(JBoltTable.PARAM_KEY);
		if (StrKit.isBlank(jboltTableJsonStr)) {
			return null;
		}
		JSONObject jsonObject = JSON.parseObject(jboltTableJsonStr);
		if (jsonObject == null || jsonObject.isEmpty()) {
			return null;
		}
		if (!jsonObject.containsKey("delete") && !jsonObject.containsKey("update") && !jsonObject.containsKey("save")
				&& !jsonObject.containsKey("form") && !jsonObject.containsKey("params")) {
			LOG.error("提交的JBoltTable数据有误，需至少包含delete|update|save|form|params其中一项");
			return null;
		}
		return getJBoltTableByJsonObject(jsonObject);
	}

	/**
	 * 从请求里获取指定model的主键ID值 指定请求参数名
	 *
	 * @param controller
	 * @param paraName
	 * @param modelClass
	 * @return
	 */
	public static Object getId(Controller controller, String paraName, Class<? extends Model> modelClass) {
		String value = controller.getPara(paraName);
		if (StrKit.isBlank(value)) {
			return null;
		}
		Table table = TableMapping.me().getTable(modelClass);
		if (table == null) {
			return null;
		}
		String primaryKey = table.getPrimaryKey()[0];
		if (StrKit.isBlank(primaryKey)) {
			return null;
		}
		try {
			return TypeConverter.me().convert(table.getColumnType(primaryKey), value);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 从请求里获取对应Model的主键ID值 url挂参 按照顺序获取
	 *
	 * @param controller
	 * @param index
	 * @param modelClass
	 * @return
	 */
	public static Object getId(Controller controller, int index, Class<? extends Model> modelClass) {
		String value = controller.getPara(index);
		if (StrKit.isBlank(value)) {
			return null;
		}
		Table table = TableMapping.me().getTable(modelClass);
		if (table == null) {
			return null;
		}
		String primaryKey = table.getPrimaryKey()[0];
		if (StrKit.isBlank(primaryKey)) {
			return null;
		}
		try {
			return TypeConverter.me().convert(table.getColumnType(primaryKey), value);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 从请求里获取dateRange参数字符串
	 *
	 * @param controller
	 * @return
	 */
	public static String getDateRangePara(Controller controller) {
		return getDateRangePara(controller, JBoltDateRange.DEFAULT_PARA_NAME);
	}

	/**
	 * 从请求里获取dateRange参数字符串
	 *
	 * @param controller
	 * @param paraName
	 * @return
	 */
	public static String getDateRangePara(Controller controller, String paraName) {
		return controller.getPara(paraName);
	}

	/**
	 * 设置dateRange变量 客户端可以用
	 *
	 * @param controller
	 * @param dateRange
	 */
	public static void setDateRange(Controller controller, String dateRange) {
		setDateRange(controller, JBoltDateRange.DEFAULT_PARA_NAME, dateRange);
	}

	/**
	 * 设置dateRange变量 客户端可以用
	 *
	 * @param controller
	 * @param dateRange
	 */
	public static void setDateRange(Controller controller, JBoltDateRange dateRange) {
		setDateRange(controller, dateRange.getParaName(), dateRange.getOriginDateRange());
	}

	/**
	 * 设置dateRange变量 客户端可以用
	 *
	 * @param controller
	 * @param dateRange
	 * @param defaultDataRangeStr
	 */
	public static void setDateRange(Controller controller, JBoltDateRange dateRange, String defaultDataRangeStr) {
		setDateRange(controller, dateRange.getParaName(), dateRange.getOriginDateRange(), defaultDataRangeStr);
	}

	/**
	 * 设置dateRange变量 客户端可以用
	 *
	 * @param controller
	 * @param attrName
	 * @param dateRange
	 */
	public static void setDateRange(Controller controller, String attrName, String dateRange) {
		controller.set(attrName, dateRange);
	}

	/**
	 * 设置dateRange变量 客户端可以用
	 *
	 * @param controller
	 * @param attrName
	 * @param dateRange
	 * @param defaultDataRangeStr
	 */
	public static void setDateRange(Controller controller, String attrName, String dateRange,
			String defaultDataRangeStr) {
		controller.set(attrName, StrKit.isBlank(dateRange) ? defaultDataRangeStr : dateRange);
	}

	/**
	 * 获取dateRange组件数据
	 *
	 * @param controller
	 * @return
	 */
	public static JBoltDateRange getDateRange(Controller controller) {
		return new JBoltDateRange(getDateRangePara(controller));
	}

	/**
	 * 获取dateRange组件数据
	 *
	 * @param controller
	 * @param paraName
	 * @return
	 */
	public static JBoltDateRange getDateRange(Controller controller, String paraName) {
		return new JBoltDateRange(getDateRangePara(controller,paraName));
	}

	/**
	 * 获取dateRange组件数据
	 *
	 * @param controller
	 * @param paraName
	 * @param type
	 * @return
	 */
	public static JBoltDateRange getDateRange(Controller controller, String paraName,String type) {
		return new JBoltDateRange(paraName, getDateRangePara(controller, paraName), type);
	}

	/**
	 * renderJson
	 *
	 * @param response
	 * @param ret
	 */
	public static void renderJson(HttpServletResponse response, Ret ret) {
		PrintWriter writer = null;
		try {
			response.setContentType("application/json; charset=utf-8");
			writer = response.getWriter();
			writer.write(JsonKit.toJson(ret));
			writer.flush();
		} catch (IOException e) {
			throw new RenderException(e);
		}
	}

	/**
	 * 返回微信小程序支付回调结果
	 *
	 * @param controller
	 * @param code
	 * @param msg
	 */
	public static void renderWxaPayResult(Controller controller, String code, String msg) {
		controller.renderText("<xml><return_code><![CDATA[" + code + "]]></return_code><return_msg><![CDATA[" + msg
				+ "]]></return_msg></xml>", ContentType.XML);
	}

	/**
	 * 返回微信小程序支付回调 success结果
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderWxaPayResultSuccess(Controller controller, String msg) {
		renderWxaPayResult(controller, "SUCCESS", msg);
	}

	/**
	 * 返回微信小程序支付回调 fail结果
	 *
	 * @param controller
	 * @param msg
	 */
	public static void renderWxaPayResultFail(Controller controller, String msg) {
		renderWxaPayResult(controller, "FAIL", msg);
	}

	/**
	 * 得到参数字符串 分割为数组
	 * @param controller
	 * @param paraName
	 * @param split
	 */
	public static String[] getParaToArray(Controller controller,String paraName,String split) {
		String paraValueStr = controller.get(paraName);
		if(StrKit.isBlank(paraValueStr)) {
			return null;
		}
		return JBoltArrayUtil.from(paraValueStr, split);
	}

	/**
	 * 得到参数字符串 分割为数组
	 * @param controller
	 * @param paraName
	 */
	public static String[] getParaToArray(Controller controller,String paraName) {
		return getParaToArray(controller, paraName,",");
	}

	/**
	 * 得到参数字符串 分割为int数组
	 * @param controller
	 * @param paraName
	 * @param split
	 */
	public static Integer[] getParaToIntArray(Controller controller,String paraName,String split) {
		String paraValueStr = controller.get(paraName);
		if(StrKit.isBlank(paraValueStr)) {
			return null;
		}
		return JBoltArrayUtil.toInt(paraValueStr, split);
	}


	/**
	 * 得到参数字符串 分割为int数组
	 * @param controller
	 * @param paraName
	 */
	public static Integer[] getParaToIntArray(Controller controller,String paraName) {
		return getParaToIntArray(controller, paraName,",");
	}

	/**
	 * 得到参数字符串 分割为long数组
	 * @param controller
	 * @param paraName
	 * @param split
	 */
	public static Long[] getParaToLongArray(Controller controller,String paraName,String split) {
		String paraValueStr = controller.get(paraName);
		if(StrKit.isBlank(paraValueStr)) {
			return null;
		}
		return JBoltArrayUtil.toLong(paraValueStr, split);
	}

	/**
	 * 得到参数字符串 分割为long数组
	 * @param controller
	 * @param paraName
	 */
	public static Long[] getParaToLongArray(Controller controller,String paraName) {
		return getParaToLongArray(controller, paraName,",");
	}

	/**
	 * 获取rangeSlider
	 * @param controller
	 * @param index
	 * @return
	 */
	public static RangeSlider getRangeSlider(Controller controller,int index){
		return getRangeSlider(controller,index,RangeSlider.SPLIT);
	}

	/**
	 * 获取rangeSlider
	 * @param controller
	 * @param index
	 * @param split
	 * @return
	 */
	public static RangeSlider getRangeSlider(Controller controller,int index,String split){
		String rangeValue = controller.get(index);
		if(StrKit.isBlank(rangeValue)){return null;}
		return RangeSlider.fromSplit(rangeValue,split);
	}

	/**
	 * 获取rangeSlider
	 * @param controller
	 * @param paraName
	 * @return
	 */
	public static RangeSlider getRangeSlider(Controller controller,String paraName){
		return getRangeSlider(controller,paraName,RangeSlider.SPLIT);
	}

	/**
	 * 获取rangeSlider
	 * @param controller
	 * @param paraName
	 * @param split
	 * @return
	 */
	public static RangeSlider getRangeSlider(Controller controller,String paraName,String split){
		String rangeValue = controller.get(paraName);
		if(StrKit.isBlank(rangeValue)){return null;}
		return RangeSlider.fromSplit(rangeValue,split);
	}
}
